// Copyright Epic Games, Inc. All Rights Reserved.

#include "MessageProcessors/AssistProcessor.h" // 包含头文件

#include "GameFramework/PlayerState.h" // 包含玩家状态类
#include "Messages/LyraVerbMessage.h" // 包含Lyra动词消息结构体
#include "Messages/LyraVerbMessageHelpers.h" // 包含Lyra动词消息辅助函数
#include "NativeGameplayTags.h" // 包含原生游戏标签定义

#include UE_INLINE_GENERATED_CPP_BY_NAME(AssistProcessor) // 包含由Unreal Header Tool生成的代码

UE_DEFINE_GAMEPLAY_TAG_STATIC(TAG_Lyra_Elimination_Message, "Lyra.Elimination.Message"); // 定义击杀消息的游戏标签
UE_DEFINE_GAMEPLAY_TAG_STATIC(TAG_Lyra_Damage_Message, "Lyra.Damage.Message"); // 定义伤害消息的游戏标签
UE_DEFINE_GAMEPLAY_TAG_STATIC(TAG_Lyra_Assist_Message, "Lyra.Assist.Message"); // 定义助攻消息的游戏标签

void UAssistProcessor::StartListening() // 开始监听消息的函数实现
{
	UGameplayMessageSubsystem& MessageSubsystem = UGameplayMessageSubsystem::Get(this); // 获取游戏消息子系统实例
	AddListenerHandle(MessageSubsystem.RegisterListener(TAG_Lyra_Elimination_Message, this, &ThisClass::OnEliminationMessage)); // 注册击杀消息监听器
	AddListenerHandle(MessageSubsystem.RegisterListener(TAG_Lyra_Damage_Message, this, &ThisClass::OnDamageMessage)); // 注册伤害消息监听器
}

void UAssistProcessor::OnDamageMessage(FGameplayTag Channel, const FLyraVerbMessage& Payload) // 处理伤害消息的函数实现
{
	if (Payload.Instigator != Payload.Target) // 如果攻击者和目标不是同一个对象
	{
		if (APlayerState* InstigatorPS = ULyraVerbMessageHelpers::GetPlayerStateFromObject(Payload.Instigator)) // 从攻击者对象获取玩家状态
		{
			if (APlayerState* TargetPS = ULyraVerbMessageHelpers::GetPlayerStateFromObject(Payload.Target)) // 从目标对象获取玩家状态
			{
				FPlayerAssistDamageTracking& Damage = DamageHistory.FindOrAdd(TargetPS); // 查找或添加目标玩家的伤害追踪记录
				float& DamageTotalFromTarget = Damage.AccumulatedDamageByPlayer.FindOrAdd(InstigatorPS); // 查找或添加攻击者对目标造成的累积伤害
				DamageTotalFromTarget += Payload.Magnitude; // 增加累积伤害值
			}
		}
	}
}

void UAssistProcessor::OnEliminationMessage(FGameplayTag Channel, const FLyraVerbMessage& Payload) // 处理击杀消息的函数实现
{
	if (APlayerState* TargetPS = Cast<APlayerState>(Payload.Target)) // 尝试将目标转换为玩家状态
	{
		// 为每个对目标造成伤害但不是击杀者的玩家授予助攻
		if (FPlayerAssistDamageTracking* DamageOnTarget = DamageHistory.Find(TargetPS)) // 查找目标玩家的伤害记录
		{
			for (const auto& KVP : DamageOnTarget->AccumulatedDamageByPlayer) // 遍历所有伤害记录
			{
				if (APlayerState* AssistPS = KVP.Key) // 获取助攻玩家状态
				{
					if (AssistPS != Payload.Instigator) // 如果助攻者不是击杀者
					{
						FLyraVerbMessage AssistMessage; // 创建新的动词消息
						AssistMessage.Verb = TAG_Lyra_Assist_Message; // 设置消息动词为助攻标签
						AssistMessage.Instigator = AssistPS; // 设置攻击者（助攻者）
						//@TODO: 从玩家状态获取默认标签或在助攻伤害期间保存最新的标签？
						//AssistMessage.InstigatorTags = ;
						AssistMessage.Target = TargetPS; // 设置目标
						AssistMessage.TargetTags = Payload.TargetTags; // 设置目标标签
						AssistMessage.ContextTags = Payload.ContextTags; // 设置上下文标签
						AssistMessage.Magnitude = KVP.Value; // 设置助攻伤害值

						UGameplayMessageSubsystem& MessageSubsystem = UGameplayMessageSubsystem::Get(this); // 获取游戏消息子系统实例
						MessageSubsystem.BroadcastMessage(AssistMessage.Verb, AssistMessage); // 广播助攻消息
					}
				}
			}

			// 清除被击杀玩家的伤害日志
			DamageHistory.Remove(TargetPS); // 从伤害记录中移除目标玩家
		}
	}
}